package com.routz.shiro_demo.user_password_sample.service;

import com.routz.shiro_demo.user_password_sample.dao.UserDao;
import com.routz.shiro_demo.user_password_sample.entity.User;
import org.apache.shiro.SecurityUtils;
import org.apache.shiro.authc.*;
import org.apache.shiro.authz.AuthorizationException;
import org.apache.shiro.crypto.RandomNumberGenerator;
import org.apache.shiro.crypto.SecureRandomNumberGenerator;
import org.apache.shiro.crypto.hash.Sha256Hash;
import org.apache.shiro.subject.Subject;
import org.apache.shiro.util.ByteSource;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.List;
import java.util.UUID;

@Service
public class UserService {
    @Autowired
    private UserDao userDao;

    public void login(User user) {
        final Subject currentUser = SecurityUtils.getSubject();

        if (!currentUser.isAuthenticated()) {
            final User udb = userDao.findUserByName(user.getName());
            if (udb == null) throw new AuthorizationException("账户不存在");

            final UsernamePasswordToken upt = new UsernamePasswordToken(user.getName(), user.getPassword(), udb.getSalt());
            upt.setRememberMe(true);
            try {
                currentUser.login(upt);
                // 更新盐值
                RandomNumberGenerator rng = new SecureRandomNumberGenerator();
                ByteSource salt = rng.nextBytes();
                userDao.updateSalt(new Sha256Hash(user.getPassword(), salt, 1024).toBase64(), salt.toBase64());
            } catch (UnknownAccountException uae) {
                throw new AuthorizationException("There is no user with username of " + upt.getPrincipal());
            } catch (IncorrectCredentialsException ice) {
                throw new AuthorizationException("Password for account " + upt.getPrincipal() + " was incorrect!");
            } catch (LockedAccountException lae) {
                throw new AuthorizationException("The account for username " + upt.getPrincipal() + " is locked.  " +
                        "Please contact your administrator to unlock it.");
            } catch (AuthenticationException ae) {
                // ... catch more exceptions here (maybe custom ones specific to your application?
                //unexpected condition?  error?
                ae.printStackTrace();
                throw new AuthorizationException("未知权限校验错误");
            }
            // 登录成功
        }
    }

    public void signUp(User user) {
        user.setId(UUID.randomUUID().toString().replaceAll("-", ""));

        RandomNumberGenerator rng = new SecureRandomNumberGenerator();
        ByteSource salt = rng.nextBytes();
        // 将盐插入数据库
        user.setSalt(salt.toBase64());
        String hashedPasswordBase64 = new Sha256Hash(user.getPassword(), salt, 1024).toBase64();
//        String hashedPasswordBase64 = new Sha256Hash(user.getPassword(), salt.toBase64(), 1024).toBase64();
        user.setPassword(hashedPasswordBase64);

        userDao.insertUser(user);
    }

    public User findUserByNameAndPassword(String name, String password) {
        return userDao.findUserByNameAndPassword(name, password);
    }

    public List<User> list() {
        return userDao.listUsers();
    }

    public String getRole(String userId) {
        return "admin";
    }

    public String getPermission(String userId) {
        return "write";
    }

    public User findUserByName(String name) {
        return userDao.findUserByName(name);
    }
}
